package com.heima.lock;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StockController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private WmLockMapper lockMapper;

    @GetMapping("/stock")
    public String stock() {
        synchronized ("abc") {
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }
        }
        return "OK";
    }

    /**
     * 分布式锁：基于mysql实现
     *
     * @return
     */
    @GetMapping("/stock1")
    public String stock1() {
        //1. 获取分布式锁：谁能往表中成功的插入数据，那么就表示谁抢到了锁
        try {
            WmLock lock = WmLock.builder().mylock("DBlock").build();
            lockMapper.insert(lock);

            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }

            //释放锁
            lockMapper.deleteById(lock.getId());
        } catch (Exception e) {
            System.out.println("没有抢到分布式锁");
        }

        return "OK";
    }


    /**
     * 分布式锁：基于redis实现
     *
     * @return
     */
    @GetMapping("/stock2")
    public String stock2() {
        //1. 获取分布式锁：谁能往redis中成功的插入数据，那么就表示谁抢到了锁
        Boolean isLock = redisTemplate.opsForValue().setIfAbsent("lock", String.valueOf(Thread.currentThread().getId()));

        if (isLock) {
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }
//            try {
//                //模拟业务耗时
//                Thread.sleep(100);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
            //释放锁
            redisTemplate.delete("lock");
        } else {
            System.out.println("没有抢到分布式锁");
        }


        return "OK";
    }

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 分布式锁：基于redisson实现
     *
     * @return
     */
    @GetMapping("/stock3")
    public String stock3() {
        //1. 获取分布式锁：谁能往redis中成功的插入数据，那么就表示谁抢到了锁
        //a.获取锁操作对象
        RLock lock = redissonClient.getLock("lock");

        //b. 通过锁对象来尝试加锁     ThreadName:
        lock.lock();            //默认锁失效时间：30秒  setnx lock 30  ThreadId
        try {
            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
//                try {
//                    //模拟业务耗时: 不固定
//                    Thread.sleep(15000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }
//            try {
//                //模拟业务耗时
//                Thread.sleep(100);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            //释放锁
//            redisTemplate.delete("lock");
//        } else{
//            System.out.println("没有抢到分布式锁");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放锁: 只能释放自己的锁
            lock.unlock();
        }


        System.out.println("没有抢到分布式锁");


        return "OK";
    }
}